import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.stat.Statistics;

import com.demo.association.manytomany.RoleDetailsDTO;
import com.demo.association.manytomany.UserDetailsDTO;
import com.demo.association.onetomany.DepartmentDTO;
import com.demo.association.onetoone.Auther;
import com.demo.association.onetoone.Biography;
import com.demo.employee.Address;
import com.demo.employee.EmployeeDTO;
import com.demo.employee.HibernateUtils;
import com.demo.employee.StudentDTO;
import com.demo.service.dao.HibernateDaoService;

public class Main {

	HibernateDaoService daoService = new HibernateDaoService();

	public static void main(String[] args) {

		// 4.0
		// reads hibernate.cfg.xml
		// JNDI - JAVA NATIVE DEVELOPMENT INTERFACE. -- RMI -- remote method
		// invocation.. -- CORBA --> common object request broker agent.
		// to generate session factory .
		Main main = new Main();
		Statistics statistics=  HibernateUtils.getSessionFactory().getStatistics();
		  System.out.println("Stats"+statistics.isStatisticsEnabled());
		   
		   statistics.setStatisticsEnabled(true);
		 //hibernate stats 
		   System.out.println("################################################################");
		   System.out.println("2nd level Cache hit:"+statistics.getSecondLevelCacheHitCount());
		   System.out.println("2nd level cache miss:"+statistics.getSecondLevelCacheMissCount());
		   System.out.println("2nd level cache put:"+statistics.getSecondLevelCachePutCount());
		   
          main.daoService.fetchObjectFromDatabase(EmployeeDTO.class, 1);
          System.out.println("################################################################");
		   System.out.println("2nd level Cache hit:"+statistics.getSecondLevelCacheHitCount());
		   System.out.println("2nd level cache miss:"+statistics.getSecondLevelCacheMissCount());
		   System.out.println("2nd level cache put:"+statistics.getSecondLevelCachePutCount());

		   main.daoService.fetchObjectFromDatabase(EmployeeDTO.class, 2);
          System.out.println("################################################################");
		   System.out.println("2nd level Cache hit:"+statistics.getSecondLevelCacheHitCount());
		   System.out.println("2nd level cache miss:"+statistics.getSecondLevelCacheMissCount());
		   System.out.println("2nd level cache put:"+statistics.getSecondLevelCachePutCount());
		   
          main.daoService.fetchObjectFromDatabase(EmployeeDTO.class, 3);
          System.out.println("################################################################");
		   System.out.println("2nd level Cache hit:"+statistics.getSecondLevelCacheHitCount());
		   System.out.println("2nd level cache miss:"+statistics.getSecondLevelCacheMissCount());
		   System.out.println("2nd level cache put:"+statistics.getSecondLevelCachePutCount());
		   
          main.daoService.fetchObjectFromDatabase(EmployeeDTO.class, 1);
          System.out.println("################################################################");
		   System.out.println("2nd level Cache hit:"+statistics.getSecondLevelCacheHitCount());
		   System.out.println("2nd level cache miss:"+statistics.getSecondLevelCacheMissCount());
		   System.out.println("2nd level cache put:"+statistics.getSecondLevelCachePutCount());
		   
          main.daoService.fetchObjectFromDatabase(EmployeeDTO.class, 2);
          System.out.println("################################################################");
		   System.out.println("2nd level Cache hit:"+statistics.getSecondLevelCacheHitCount());
		   System.out.println("2nd level cache miss:"+statistics.getSecondLevelCacheMissCount());
		   System.out.println("2nd level cache put:"+statistics.getSecondLevelCachePutCount());
		   
          
		// main.insertoneTomanyEmployeDeptDetails();

		//main.searchEmployeeForSalaryLessthan(12000);
		//main.insertEmployeForDepartment(3);
		// main.insertAutherDetails();

		// HibernateDaoService hibernateDaoService=new HibernateDaoService();

		/*
		 * 
		 * Biography
		 * biography=(Biography)hibernateDaoService.fetchObjectFromDatabase
		 * (Biography.class, 1); System.out.println(biography.getAuther());
		 */
		/*
		 * System.out.println("Now accessing author details..."); Auther
		 * auther=(
		 * Auther)hibernateDaoService.fetchObjectFromDatabase(Auther.class, 1);
		 * System.out.println(auther);
		 */
	}



	@SuppressWarnings("unchecked")
	public void insertUserDetails(){
		List<RoleDetailsDTO> roleList=(List<RoleDetailsDTO>) daoService.loadAllRowsForClass(RoleDetailsDTO.class);

		if(null!=roleList && roleList.size()>0){
			/*  RoleDetailsDTO detailsDTO=new RoleDetailsDTO();
			  detailsDTO.setRoleId("ROLE_USER");
			  detailsDTO.setRoleDesc("");*/

			UserDetailsDTO userDetailsDTO=new UserDetailsDTO();
			userDetailsDTO.setUserName("Rajeev");;
			userDetailsDTO.setAddress("Delhi");
			userDetailsDTO.setSalary(2000.5);
			userDetailsDTO.setRoleList(roleList);
			daoService.insertNewRow(userDetailsDTO);

		}else {
			System.out.println("NO role exist in database please insert roles.");
		}

	}

	public void insertoneTomanyEmployeDeptDetails() {

		DepartmentDTO departmentDTO = new DepartmentDTO("IT");
		departmentDTO.getEmployeeList()
		.add(new com.demo.association.onetomany.EmployeeDTO("Vaibhav",
				12000));
		departmentDTO.getEmployeeList().add(
				new com.demo.association.onetomany.EmployeeDTO("Vibhanshu",
						13000));

		daoService.insertNewRow(departmentDTO);
		System.out
		.println("Depart details with employee inserted successfully !!");

	}

	public void insertEmployeForDepartment(int deptId) {

		DepartmentDTO departmentDTO = (DepartmentDTO) daoService
				.fetchObjectFromDatabase(DepartmentDTO.class, deptId);
		com.demo.association.onetomany.EmployeeDTO employeeDTO = new com.demo.association.onetomany.EmployeeDTO(
				"Rajeev", 2100);
		employeeDTO.setDepartment(departmentDTO);
		daoService.insertNewRow(employeeDTO);

	}

	public void searchEmployeeForSalaryLessthan(double salary) {

		// criteria
		Session session = HibernateUtils.getSessionFactory().openSession();
		/*   
		 *           SQLQuery sqlQuery=        session.createSQLQuery("SELECT * FROM DFLKAJFLK ADFA F F")
            		  sqlQuery.list();

		 */
		Criteria criteria = session.createCriteria(com.demo.association.onetomany.EmployeeDTO.class); //SELECT * FROM EMPLOYEE2 
		criteria.add(Restrictions.le("salary",salary));
		//criteria.add(Restrictions.eq("department.departName", "IT"));
		//criteria.add(Restrictions.or(predicates))
		criteria.addOrder(Order.asc("name"));
		List<com.demo.association.onetomany.EmployeeDTO> empList= criteria.list();
		if(null!=empList &&  empList.size()>0){
			System.out.println("no of employee found :"+empList.size());
			for (com.demo.association.onetomany.EmployeeDTO employeeDTO : empList) {
				System.out.println("Empname :"+employeeDTO.getName()+" ---- department --"+employeeDTO.getDepartment().getDepartName());
			}
		}
		//hql hibernate query language
		//SQL 
	}

	public void insertAutherDetails() {
		Session session = HibernateUtils.getSessionFactory().openSession();
		session.beginTransaction();

		Auther auther = new Auther();
		auther.setAutherName("Vaibhav");
		auther.setAutherDegree("MCA");

		// session.persist(auther); //to get initilized primary key /// insert
		// query executes when transaction commits.

		Biography biography = new Biography();

		// biography.setId(auther.getAutherId()); //set that primary key to
		// biography

		biography.setBiographyDetails("this is dummy biography!");

		auther.setBiography(biography);
		biography.setAuther(auther);

		session.save(auther); // final save

		session.getTransaction().commit();
		session.flush();
		session.close();
	}

	public void deleteAuther(int autherId) {

		Session session = HibernateUtils.getSessionFactory().openSession();

		session.beginTransaction();
		Auther auther = (Auther) session.get(Auther.class, autherId);
		session.delete(auther);
		session.getTransaction().commit();
		session.close();
	}

	public void insertStudent() {
		StudentDTO studentDTO = new StudentDTO();
		studentDTO.setName("Demo student");
		studentDTO.setAge(24);

		Session session = HibernateUtils.getSessionFactory().openSession();
		Transaction transaction = session.beginTransaction();
		session.save(studentDTO);
		transaction.commit();
		session.flush();
		session.clear();

	}

	// CRUD create read update delete ,,, custom selection where clause in sql
	public EmployeeDTO getEmployeeDetailsById(int empId) {
		System.out.println("inside get employeedetails by id method");
		Session session = HibernateUtils.getSessionFactory().openSession();
		Transaction transaction = session.beginTransaction();
		// EmployeeDTO employeeDTO= (EmployeeDTO) session.get(EmployeeDTO.class,
		// empId);//
		EmployeeDTO employeeDTO = (EmployeeDTO) session.get(EmployeeDTO.class,
				empId);
		// select * from EMPLOYEE where ID='220'
		// select name from EMPLOYEE WHERE ID='220';
		System.out
		.println("till this line no select query would be perfromed !!");
		System.out.println("query would be executed...");
		transaction.commit();
		session.flush();
		session.close();
		System.out.println("after fetching employee details object !!");
		return employeeDTO;

	}

	public void updateEmployeeDetails(String upatedName, int empId) {

		Session session = HibernateUtils.getSessionFactory().openSession();
		Transaction transaction = session.beginTransaction();
		EmployeeDTO dto = (EmployeeDTO) session.get(EmployeeDTO.class, empId);
		dto.setName(upatedName);
		session.update(dto);
		transaction.commit();
		session.flush();
		session.close();
		System.out.println("Object updated successfully");

	}

	public void deleteEmployeeDetailsForId(int empId) {
		Session session = HibernateUtils.getSessionFactory().openSession();
		Transaction transaction = session.beginTransaction();
		// ?
		// object state in hibernate
		// only persitent object can be deleted by session.delete();
		// session.delete(object);
	}

	// inserting data into database
	public void insertEmployeeDetails() {

		EmployeeDTO employeeDTO = new EmployeeDTO();
		employeeDTO.setName("New User");
		employeeDTO.setAge(25);


		/*	employeeDTO.getAddresses().add(address);
		employeeDTO.getAddresses().add(address1);

		 */		Session session = HibernateUtils.getSessionFactory().openSession();

		 try {
			 session.beginTransaction();
			 // it maintains cache ( first level cache ( session level ))

			 System.out.println("empid " + employeeDTO.getId());

			 // before save empDto is in transient state

			 session.save(employeeDTO);
			 // now empDTo is avalable in persitent state..

			 /*
			  * employeeDTO.setAge(65); session.update(employeeDTO); //update
			  * employeeDTO.setAge(12); session.update(employeeDTO); //update
			  */
			 System.out.println("going to commit tranaction");
			 // minimum hit to database

		 } catch (HibernateException e) {
			 e.printStackTrace();
			 session.getTransaction().rollback();
		 } finally {
			 session.flush();
			 session.getTransaction().commit();
			 session.close();
		 }
		 System.out.println("Employee details inserted successfully !");

	}

}
